import axios from 'axios'
import { Toast } from 'antd-mobile'
import { getTokenInfo, setTokenInfo } from './storage'
import store from '@/store'
import { logout, setToken } from '@/store/actions/login'
import { history } from './history'

const http = axios.create({
  baseURL: 'http://geek.itheima.net/v1_0',
  timeout: 5000,
})
// 2. 设置请求拦截器和响应拦截器
http.interceptors.request.use((config) => {
  if (getTokenInfo().token) {
    config.headers.Authorization = 'Bearer ' + getTokenInfo().token
  }
  return config
})

http.interceptors.response.use(
  (response) => {
    return response.data
  },
  async (error) => {
    // 如果是网络错误
    if (!error.response) {
      Toast.show({ icon: 'fail', content: '服务器繁忙，请稍后再试' })
      return Promise.reject(error)
    }
    // 如果有响应，但是不是401错误
    if (error.response.status !== 401) {
      Toast.show({
        content: error.response.data.message,
      })
      return Promise.reject(error)
    }
    const { refresh_token } = getTokenInfo()
    // 如果是401错误
    // 如果没有token或者刷新token
    if (!refresh_token) {
      // 跳转到登录页，并携带当前正在访问的地址
      Toast.show({ icon: 'fail', content: '登录过期，请重新登录' })
      return Promise.reject(error)
    }
    // 如果有token，且是401错误
    try {
      // 通过 Refresh Token 换取新 Token
      // 特别说明：这个地方发请求的时候，不能使用新建的 http 实例去请求，要用默认实例 axios 去请求！
      // 否则会因 http 实例的请求拦截器的作用，携带上老的 token 而不是 refresh_token
      const res = await axios.put(
        `${error.config.baseURL}/authorizations`,
        null,
        {
          headers: {
            Authorization: `Bearer ${refresh_token}`,
          },
        }
      )

      // 将新换到的 Token 信息保存到 Redux 和 LocalStorage 中
      const tokenInfo = {
        token: res.data.data.token,
        refresh_token,
      }

      setTokenInfo(tokenInfo)
      store.dispatch(setToken(tokenInfo))

      // 重新发送之前因 Token 无效而失败的请求
      // return instance(error.config)
    } catch (error) {
      // 如果换取token失败

      store.dispatch(logout())
      // 跳转到登录页，并携带上当前正在访问的页面，等登录成功后再跳回该页面
      history.replace('/login', {
        from: history.location,
      })
      Toast.info('登录信息失效')
      return Promise.reject(error)
    }
  }
)

export default http
